home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Plotting / aa_Intel_Only / Gnuplot / GnuplotSource / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  12.9 KB  |  630 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: util.c%v 3.38.119.1 1993/04/25 23:55:53 woo Exp woo $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - util.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  * 
  25.  *   Original Software:
  26.  *     Thomas Williams,  Colin Kelley.
  27.  * 
  28.  *   Gnuplot 2.0 additions:
  29.  *       Russell Lang, Dave Kotz, John Campbell.
  30.  *
  31.  *   Gnuplot 3.0 additions:
  32.  *       Gershon Elber and many others.
  33.  * 
  34.  * Send your comments or suggestions to 
  35.  *  info-gnuplot@dartmouth.edu.
  36.  * This is a mailing list; to join it send a note to 
  37.  *  info-gnuplot-request@dartmouth.edu.  
  38.  * Send bug reports to
  39.  *  bug-gnuplot@dartmouth.edu.
  40.  */
  41.  
  42. #include <ctype.h>
  43. #include <setjmp.h>
  44. #include <stdio.h>
  45. #include <errno.h>
  46. #include "plot.h"
  47.  
  48. TBOOLEAN screen_ok;
  49.     /* TRUE if command just typed; becomes FALSE whenever we
  50.         send some other output to screen.  If FALSE, the command line
  51.         will be echoed to the screen before the ^ error message. */
  52.  
  53. #ifndef vms
  54. #if !defined(__ZTC__) && !defined(__PUREC__)
  55. #if !defined(__MSC__)
  56. extern int errno;
  57. #endif
  58. extern int sys_nerr;
  59. extern char *sys_errlist[];
  60. #endif
  61. #endif /* vms */
  62.  
  63. extern char input_line[];
  64. extern struct lexical_unit token[];
  65. #ifdef _Windows
  66. extern jmp_buf far env;    /* from plot.c */
  67. #else
  68. extern jmp_buf env;    /* from plot.c */
  69. #endif
  70. extern int inline_num;        /* from command.c */
  71. extern TBOOLEAN interactive;    /* from plot.c */
  72. extern char *infile_name;    /* from plot.c */
  73.  
  74. #ifdef sequent
  75. extern char *index();
  76. #else
  77. extern char *strchr();
  78. #endif
  79.  
  80. #ifndef AMIGA_AC_5
  81. extern double sqrt(), atan2();
  82. #endif
  83.  
  84. /*
  85.  * chr_in_str() compares the characters in the string of token number t_num
  86.  * with c, and returns TRUE if a match was found.
  87.  */
  88. chr_in_str(t_num, c)
  89. int t_num;
  90. char c;
  91. {
  92. register int i;
  93.  
  94.     if (!token[t_num].is_token)
  95.         return(FALSE);                /* must be a value--can't be equal */
  96.     for (i = 0; i < token[t_num].length; i++) {
  97.         if (input_line[token[t_num].start_index+i] == c)
  98.             return(TRUE);
  99.         }
  100.     return FALSE;
  101. }
  102.  
  103.  
  104. /*
  105.  * equals() compares string value of token number t_num with str[], and
  106.  *   returns TRUE if they are identical.
  107.  */
  108. equals(t_num, str)
  109. int t_num;
  110. char *str;
  111. {
  112. register int i;
  113.  
  114.     if (!token[t_num].is_token)
  115.         return(FALSE);                /* must be a value--can't be equal */
  116.     for (i = 0; i < token[t_num].length; i++) {
  117.         if (input_line[token[t_num].start_index+i] != str[i])
  118.             return(FALSE);
  119.         }
  120.     /* now return TRUE if at end of str[], FALSE if not */
  121.     return(str[i] == '\0');
  122. }
  123.  
  124.  
  125.  
  126. /*
  127.  * almost_equals() compares string value of token number t_num with str[], and
  128.  *   returns TRUE if they are identical up to the first $ in str[].
  129.  */
  130. almost_equals(t_num, str)
  131. int t_num;
  132. char *str;
  133. {
  134. register int i;
  135. register int after = 0;
  136. register start = token[t_num].start_index;
  137. register length = token[t_num].length;
  138.  
  139.     if (!token[t_num].is_token)
  140.         return(FALSE);                /* must be a value--can't be equal */
  141.     for (i = 0; i < length + after; i++) {
  142.         if (str[i] != input_line[start + i]) {
  143.             if (str[i] != '$')
  144.                 return(FALSE);
  145.             else {
  146.                 after = 1;
  147.                 start--;    /* back up token ptr */
  148.                 }
  149.             }
  150.         }
  151.  
  152.     /* i now beyond end of token string */
  153.  
  154.     return(after || str[i] == '$' || str[i] == '\0');
  155. }
  156.  
  157.  
  158.  
  159. isstring(t_num)
  160. int t_num;
  161. {
  162.     
  163.     return(token[t_num].is_token &&
  164.            (input_line[token[t_num].start_index] == '\'' ||
  165.            input_line[token[t_num].start_index] == '\"'));
  166. }
  167.  
  168.  
  169. isnumber(t_num)
  170. int t_num;
  171. {
  172.     return(!token[t_num].is_token);
  173. }
  174.  
  175.  
  176. isletter(t_num)
  177. int t_num;
  178. {
  179.     return(token[t_num].is_token &&
  180.             ((isalpha(input_line[token[t_num].start_index]))||
  181.              (input_line[token[t_num].start_index] == '_')));
  182. }
  183.  
  184.  
  185. /*
  186.  * is_definition() returns TRUE if the next tokens are of the form
  187.  *   identifier =
  188.  *        -or-
  189.  *   identifier ( identifer {,identifier} ) =
  190.  */
  191. is_definition(t_num)
  192. int t_num;
  193. {
  194.     /* variable? */
  195.     if(isletter(t_num) && equals(t_num+1,"="))
  196.         return 1;
  197.  
  198.     /* function? */
  199.     /* look for dummy variables */
  200.     if(isletter(t_num) && equals(t_num+1,"(") && isletter(t_num+2)) {
  201.         t_num += 3;  /* point past first dummy */
  202.         while(equals(t_num,",")) {
  203.             if(!isletter(++t_num))
  204.                 return 0;
  205.             t_num += 1;
  206.         }
  207.         return(equals(t_num,")") && equals(t_num+1,"="));
  208.     }
  209.  
  210.     /* neither */
  211.     return 0;
  212. }
  213.  
  214.  
  215.  
  216. /*
  217.  * copy_str() copies the string in token number t_num into str, appending
  218.  *   a null.  No more than MAX_ID_LEN chars are copied.
  219.  */
  220. copy_str(str, t_num)
  221. char str[];
  222. int t_num;
  223. {
  224. register int i = 0;
  225. register int start = token[t_num].start_index;
  226. register int count;
  227.  
  228.     if ((count = token[t_num].length) > MAX_ID_LEN)
  229.         count = MAX_ID_LEN;
  230.     do {
  231.         str[i++] = input_line[start++];
  232.         } while (i != count);
  233.     str[i] = '\0';
  234. }
  235.  
  236.  
  237. /*
  238.  * quote_str() does the same thing as copy_str, except it ignores the
  239.  *   quotes at both ends.  This seems redundant, but is done for
  240.  *   efficency.
  241.  */
  242. quote_str(str, t_num)
  243. char str[];
  244. int t_num;
  245. {
  246. register int i = 0;
  247. register int start = token[t_num].start_index + 1;
  248. register int count;
  249.  
  250.     if ((count = token[t_num].length - 2) > MAX_ID_LEN)
  251.         count = MAX_ID_LEN;
  252.     if (count>0) {
  253.         do {
  254.             str[i++] = input_line[start++];
  255.             } while (i != count);
  256.     }
  257.     str[i] = '\0';
  258. }
  259.  
  260.  
  261. /*
  262.  * quotel_str() does the same thing as quote_str, except it uses
  263.  * MAX_LINE_LEN instead of MAX_ID_LEN. 
  264.  */ 
  265. quotel_str(str, t_num) 
  266. char str[]; 
  267. int t_num; 
  268. {
  269. register int i = 0;
  270. register int start = token[t_num].start_index + 1;
  271. register int count;
  272.  
  273.     if ((count = token[t_num].length - 2) > MAX_LINE_LEN)
  274.         count = MAX_LINE_LEN;
  275.     if (count>0) {
  276.         do {
  277.             str[i++] = input_line[start++];
  278.             } while (i != count);
  279.     }
  280.     str[i] = '\0';
  281. }
  282.  
  283.  
  284. /*
  285.  *    capture() copies into str[] the part of input_line[] which lies between
  286.  *    the begining of token[start] and end of token[end].
  287.  */
  288. capture(str,start,end)
  289. char str[];
  290. int start,end;
  291. {
  292. register int i,e;
  293.  
  294.     e = token[end].start_index + token[end].length;
  295.     for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
  296.         *str++ = input_line[i];
  297.     *str = '\0';
  298. }
  299.  
  300.  
  301. /*
  302.  *    m_capture() is similar to capture(), but it mallocs storage for the
  303.  *  string.
  304.  */
  305. m_capture(str,start,end)
  306. char **str;
  307. int start,end;
  308. {
  309. register int i,e;
  310. register char *s;
  311.  
  312.     if (*str)        /* previous pointer to malloc'd memory there */
  313.         free(*str);
  314.     e = token[end].start_index + token[end].length;
  315.     *str = alloc((unsigned long)(e - token[start].start_index + 1), "string");
  316.      s = *str;
  317.      for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
  318.       *s++ = input_line[i];
  319.      *s = '\0';
  320. }
  321.  
  322.  
  323. /*
  324.  *    m_quote_capture() is similar to m_capture(), but it removes
  325.     quotes from either end if the string.
  326.  */
  327. m_quote_capture(str,start,end)
  328. char **str;
  329. int start,end;
  330. {
  331. register int i,e;
  332. register char *s;
  333.  
  334.     if (*str)        /* previous pointer to malloc'd memory there */
  335.         free(*str);
  336.     e = token[end].start_index + token[end].length-1;
  337.     *str = alloc((unsigned long)(e - token[start].start_index + 1), "string");
  338.      s = *str;
  339.     for (i = token[start].start_index + 1; i < e && input_line[i] != '\0'; i++)
  340.      *s++ = input_line[i];
  341.     *s = '\0';
  342. }
  343.  
  344.  
  345. convert(val_ptr, t_num)
  346. struct value *val_ptr;
  347. int t_num;
  348. {
  349.     *val_ptr = token[t_num].l_val;
  350. }
  351.  
  352. static char *num_to_str(r)
  353. double r;
  354. {
  355.     static i = 0;
  356.     static char s[4][20];
  357.     int j = i++;
  358.  
  359.     if ( i > 3 ) i = 0;
  360.  
  361.     sprintf( s[j], "%g", r );
  362. #ifdef sequent
  363.     if ( index( s[j], '.' ) == NULL &&
  364.          index( s[j], 'e' ) == NULL &&
  365.          index( s[j], 'E' ) == NULL )
  366. #else
  367.     if ( strchr( s[j], '.' ) == NULL &&
  368.          strchr( s[j], 'e' ) == NULL &&
  369.          strchr( s[j], 'E' ) == NULL )
  370. #endif
  371.         strcat( s[j], ".0" );
  372.  
  373.     return s[j];
  374.  
  375. disp_value(fp,val)
  376. FILE *fp;
  377. struct value *val;
  378. {
  379.     switch(val->type) {
  380.         case INTGR:
  381.             fprintf(fp,"%d",val->v.int_val);
  382.             break;
  383.         case CMPLX:
  384.             if (val->v.cmplx_val.imag != 0.0 )
  385.                 fprintf(fp,"{%s, %s}",
  386.                     num_to_str(val->v.cmplx_val.real),
  387.                     num_to_str(val->v.cmplx_val.imag));
  388.             else
  389.                 fprintf(fp,"%s",
  390.                     num_to_str(val->v.cmplx_val.real));
  391.             break;
  392.         default:
  393.             int_error("unknown type in disp_value()",NO_CARET);
  394.     }
  395. }
  396.  
  397.  
  398. double
  399. real(val)        /* returns the real part of val */
  400. struct value *val;
  401. {
  402.     switch(val->type) {
  403.         case INTGR:
  404.             return((double) val->v.int_val);
  405.         case CMPLX:
  406.             return(val->v.cmplx_val.real);
  407.     }
  408.     int_error("unknown type in real()",NO_CARET);
  409.     /* NOTREACHED */
  410.     return((double)0.0);
  411. }
  412.  
  413.  
  414. double
  415. imag(val)        /* returns the imag part of val */
  416. struct value *val;
  417. {
  418.     switch(val->type) {
  419.         case INTGR:
  420.             return(0.0);
  421.         case CMPLX:
  422.             return(val->v.cmplx_val.imag);
  423.     }
  424.     int_error("unknown type in imag()",NO_CARET);
  425.     /* NOTREACHED */
  426.     return((double)0.0);
  427. }
  428.  
  429.  
  430.  
  431. double
  432. magnitude(val)        /* returns the magnitude of val */
  433. struct value *val;
  434. {
  435.     switch(val->type) {
  436.         case INTGR:
  437.             return((double) abs(val->v.int_val));
  438.         case CMPLX:
  439.             return(sqrt(val->v.cmplx_val.real*
  440.                     val->v.cmplx_val.real +
  441.                     val->v.cmplx_val.imag*
  442.                     val->v.cmplx_val.imag));
  443.     }
  444.     int_error("unknown type in magnitude()",NO_CARET);
  445.     /* NOTREACHED */
  446.     return((double)0.0);
  447. }
  448.  
  449.  
  450.  
  451. double
  452. angle(val)        /* returns the angle of val */
  453. struct value *val;
  454. {
  455.     switch(val->type) {
  456.         case INTGR:
  457.             return((val->v.int_val > 0) ? 0.0 : Pi);
  458.         case CMPLX:
  459.             if (val->v.cmplx_val.imag == 0.0) {
  460.                 if (val->v.cmplx_val.real >= 0.0)
  461.                     return(0.0);
  462.                 else
  463.                     return(Pi);
  464.             }
  465.             return(atan2(val->v.cmplx_val.imag,
  466.                      val->v.cmplx_val.real));
  467.     }
  468.     int_error("unknown type in angle()",NO_CARET);
  469.     /* NOTREACHED */
  470.     return((double)0.0);
  471. }
  472.  
  473.  
  474. struct value *
  475. Gcomplex(a,realpart,imagpart)
  476. struct value *a;
  477. double realpart, imagpart;
  478. {
  479.     a->type = CMPLX;
  480.     a->v.cmplx_val.real = realpart;
  481.     a->v.cmplx_val.imag = imagpart;
  482.     return(a);
  483. }
  484.  
  485.  
  486. struct value *
  487. Ginteger(a,i)
  488. struct value *a;
  489. int i;
  490. {
  491.     a->type = INTGR;
  492.     a->v.int_val = i;
  493.     return(a);
  494. }
  495.  
  496.  
  497.  
  498. os_error(str,t_num)
  499. char str[];
  500. int t_num;
  501. {
  502. #ifdef vms
  503. static status[2] = {1, 0};        /* 1 is count of error msgs */
  504. #endif
  505.  
  506. register int i;
  507.  
  508.     /* reprint line if screen has been written to */
  509.  
  510.     if (t_num != NO_CARET) {        /* put caret under error */
  511.         if (!screen_ok)
  512.             fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
  513.  
  514.         for (i = 0; i < sizeof(PROMPT) - 1; i++)
  515.             (void) putc(' ',stderr);
  516.         for (i = 0; i < token[t_num].start_index; i++) {
  517.             (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  518.             }
  519.         (void) putc('^',stderr);
  520.         (void) putc('\n',stderr);
  521.     }
  522.  
  523.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  524.         (void) putc(' ',stderr);
  525.     fprintf(stderr,"%s\n",str);
  526.  
  527.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  528.         (void) putc(' ',stderr);
  529.      if (!interactive)
  530.       if (infile_name != NULL)
  531.         fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
  532.       else
  533.         fprintf(stderr,"line %d: ", inline_num);
  534.  
  535.  
  536. #ifdef vms
  537.     status[1] = vaxc$errno;
  538.     sys$putmsg(status);
  539.     (void) putc('\n',stderr);
  540. #else
  541. #ifdef __ZTC__
  542.     fprintf(stderr,"error number %d\n\n",errno);
  543. #else
  544.     if (errno >= sys_nerr)
  545.         fprintf(stderr, "unknown errno %d\n\n", errno);
  546.     else
  547.         fprintf(stderr,"(%s)\n\n",sys_errlist[errno]);
  548. #endif
  549. #endif
  550.  
  551.     longjmp(env, TRUE);    /* bail out to command line */
  552. }
  553.  
  554.  
  555. int_error(str,t_num)
  556. char str[];
  557. int t_num;
  558. {
  559. register int i;
  560.  
  561.     /* reprint line if screen has been written to */
  562.  
  563.     if (t_num != NO_CARET) {        /* put caret under error */
  564.         if (!screen_ok)
  565.             fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
  566.  
  567.         for (i = 0; i < sizeof(PROMPT) - 1; i++)
  568.             (void) putc(' ',stderr);
  569.         for (i = 0; i < token[t_num].start_index; i++) {
  570.             (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  571.             }
  572.         (void) putc('^',stderr);
  573.         (void) putc('\n',stderr);
  574.     }
  575.  
  576.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  577.         (void) putc(' ',stderr);
  578.      if (!interactive)
  579.       if (infile_name != NULL)
  580.         fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
  581.       else
  582.         fprintf(stderr,"line %d: ", inline_num);
  583.      fprintf(stderr,"%s\n\n", str);
  584.  
  585.     longjmp(env, TRUE);    /* bail out to command line */
  586. }
  587.  
  588. /* Lower-case the given string (DFK) */
  589. /* Done in place. */
  590. void
  591. lower_case(s)
  592.      char *s;
  593. {
  594.   register char *p = s;
  595.  
  596.   while (*p != '\0') {
  597.     if (isupper(*p))
  598.      *p = tolower(*p);
  599.     p++;
  600.   }
  601. }
  602.  
  603. /* Squash spaces in the given string (DFK) */
  604. /* That is, reduce all multiple white-space chars to single spaces */
  605. /* Done in place. */
  606. void
  607. squash_spaces(s)
  608.      char *s;
  609. {
  610.   register char *r = s;        /* reading point */
  611.   register char *w = s;        /* writing point */
  612.   TBOOLEAN space = FALSE;        /* TRUE if we've already copied a space */
  613.  
  614.   for (w = r = s; *r != '\0'; r++) {
  615.      if (isspace(*r)) {
  616.         /* white space; only copy if we haven't just copied a space */
  617.         if (!space) {
  618.             space = TRUE;
  619.             *w++ = ' ';
  620.         }                /* else ignore multiple spaces */
  621.      } else {
  622.         /* non-space character; copy it and clear flag */
  623.         *w++ = *r;
  624.         space = FALSE;
  625.      }
  626.   }
  627.   *w = '\0';                /* null terminate string */
  628. }
  629.